import { _decorator, AudioClip, Button, Color, Component, director, EditBox, error, find, game, Label, Node, resources, Vec3 } from 'cc';
import { GLOBALUtil } from './GlobalUtil';
import { GLOBALVar } from './GlobalVar';
import { SoundManager } from './SoundManager';
import { LocalVarManager } from './LocalVarManager';
const { ccclass, property } = _decorator;

enum LoginState {
    Login,  //登录
    Register,   //注册
    Forget,  //忘记密码
    Change, //修改密码
}
type UserData = {
    nickname: string,
    avatar_url: string
}
@ccclass('LoginManager')
export class LoginManager extends Component {
    @property({type: Node, tooltip: "登陆面板"})
    private LoginPanel: Node | null = null;
    @property({type: Node, tooltip: "注册面板"})
    private RegisterPanel: Node | null = null;
    @property({type: Node, tooltip: "忘记密码"})
    private ForgetPanel: Node | null = null;

    private MessageNode: Node;
    private state: LoginState | null = null;
    start() {
        
    }

    update(deltaTime: number) {
        
    }

    onClickExitBtn() {
        game.end();
    }
    
    onClickOpenUI(event: Event, data: string) {
        resources.load('Audios/PVZ/awooga', AudioClip, (err, clip) => {
            if (err) {
                console.error(err);
                return;
            }
            const soundManager = SoundManager.getInstance();
            soundManager.playSFX(clip);
        })
        switch (data) {
            case "Login":
                this.state = LoginState.Login;
                this.loginByToken();
                break;
            case "Register":
                this.state = LoginState.Register;
                this.RegisterPanel.active = true;
                break;
            case "Forget":
                this.state = LoginState.Forget;
                this.LoginPanel.active = false;
                this.ForgetPanel.active = true;
                break;
        }
    }

    //用token免密登录
    async loginByToken() {
        const isLoginByToken = localStorage.getItem("isLoginByToken");
        if (isLoginByToken === "false") {
            this.LoginPanel.active = true;
        } else {
            const token = localStorage.getItem(LocalVarManager.getInstance().token);
            if (token == null) {
                //没有储存token说明是下载后第一次在这个设备上登录
                this.LoginPanel.active = true;
                return;
            }
            try {
                const response = await GLOBALUtil.requestLoginByToken();
                localStorage.setItem("isLoginByToken", "true");
                director.loadScene("MenuScene");
                GLOBALUtil.LoadMessage(true, '登录成功！', find("Canvas"), new Vec3(60, 800, 0), true, 3, new Vec3(-300, 800, 0));
            } catch (error) {
                GLOBALUtil.LoadMessage(true, '身份认证失效\n请重新登录！', find("Canvas"), new Vec3(60, 800, 0), true, 2, new Vec3(-300, 800, 0));
                localStorage.setItem("isLoginByToken", "false");
                this.LoginPanel.active = true;
                return;
            }
        }
    }
    async onClickLogin(event: Event) {
        const NodeTarget = event.target as unknown as Node;
        const email = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxUserName").getComponent(EditBox).string
        const password = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxPassword").getComponent(EditBox).string
        const HashPassword = GLOBALUtil.hashPassword(password);
        if (!GLOBALUtil.validateEmail(email)) {
            this.messageTip(true, "邮箱格式有误！", this.LoginPanel, new Vec3(50, 950, 0))
        } else {
            //邮箱格式正确的情况下
            const LoginData = {
                email: email,
                password: HashPassword
            }
            try {
                const response = await GLOBALUtil.requestLogin(LoginData);
                console.log(response.msg);
                //登录成功后
                localStorage.setItem('token', response.token);
                //记录上一次正确登录的邮箱
                localStorage.setItem("lastLoginEmail", email);
                // 提前加载头像这些资源后跳转界面
                const userData = await GLOBALUtil.getUserInfo() as UserData;
                GLOBALVar.avatarUrlCache = userData.avatar_url;
                GLOBALVar.nicknameCache = userData.nickname;
                GLOBALUtil.loadNetImage(GLOBALVar.avatarUrlCache, (Sp) => {
                    GLOBALVar.avatarSpriteCache = Sp;
                    //登录成功后设置自动登录isLoginByToken
                    localStorage.setItem("isLoginByToken", "true");
                    director.loadScene('MenuScene');
                })
            } catch (error) {
                console.log(error.message);
                this.messageTip(true, error.message, this.LoginPanel, new Vec3(50, 950, 0));
            }
        }
    }

    onClickRegister(event: Event) {
        const NodeTarget = event.target as unknown as Node;
        const email = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxUserName").getComponent(EditBox).string;
        const password = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxPassword").getComponent(EditBox).string;
        const password2 = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxPassword2").getComponent(EditBox).string;
        const AuthCode = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxAuthCode").getComponent(EditBox).string;

        //检查邮箱格式
        if (!GLOBALUtil.validateEmail(email)) {
            this.messageTip(true, "邮箱格式有误！", this.RegisterPanel, new Vec3(50, 950, 0));
            return;
        }

        // 检查密码是否包含空格和中文
        const passwordRegex = /^[^\s\u4e00-\u9fa5]+$/;
        if (!passwordRegex.test(password)) {
            this.messageTip(true, "密码不能包含空格或中文！", this.RegisterPanel, new Vec3(50, 950, 0));
            return;
        }

        //邮箱格式正确后校验两次密码是否相同
        if (password != password2) {
            this.messageTip(true, "两次输入的密码不同！", this.RegisterPanel, new Vec3(50, 950, 0));
            return;
        }

        if (password.length < 6 || password.length > 16) {
            this.messageTip(true, "密码长度必须\n在6到16位之间！", this.RegisterPanel, new Vec3(50, 950, 0));
            return;
        }

        if (AuthCode.length == 0) {
            this.messageTip(true, "验证码不能为空！", this.RegisterPanel, new Vec3(50, 950, 0));
            return;
        }

        const RegisterData = {
            email: email,
            password: GLOBALUtil.hashPassword(password),
            AuthCode: AuthCode
        }
        GLOBALUtil.sendXMLMessage('POST', GLOBALVar.SERVER_ADDRESS + "/Login/RequestRegister", true, RegisterData)
        .then(xhr => {
            // const response = JSON.parse(xhr.response);
            console.log(xhr.response);
            this.messageTip(true, xhr.response, this.RegisterPanel, new Vec3(50, 950, 0));
        }).catch(error => {
            console.log(error.message);
            this.messageTip(true, error.message, this.RegisterPanel, new Vec3(50, 950, 0));
        })

    }

    onClickForget(event: Event) {
        const NodeTarget = event.target as unknown as Node;
        const email = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxUserName").getComponent(EditBox).string;
        const newPassword = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxPassword").getComponent(EditBox).string;
        const AuthCode = NodeTarget.parent.getChildByPath("AccountNode/UserNode/EditBoxAuthCode").getComponent(EditBox).string;

        if (!GLOBALUtil.validateEmail(email)) {
            this.messageTip(true, "邮箱格式有误！", this.ForgetPanel, new Vec3(50, 950, 0))
            return;
        }
        if (newPassword.length < 6 || newPassword.length > 16) {
            this.messageTip(true, "密码长度必须\n在6到16位之间！", this.ForgetPanel, new Vec3(50, 950, 0));
            return;
        }
        if (AuthCode.length == 0) {
            this.messageTip(true, "验证码不能为空！", this.ForgetPanel, new Vec3(50, 950, 0));
            return;
        }
        const ForgetData = {
            email: email,
            password: GLOBALUtil.hashPassword(newPassword),
            AuthCode: AuthCode
        }
        GLOBALUtil.sendXMLMessage('POST', GLOBALVar.SERVER_ADDRESS + "/Login/RequestForget", true, ForgetData)
        .then(xhr => {
            const response = xhr.response;
            this.messageTip(true, response, this.ForgetPanel, new Vec3(50, 950, 0));
        }).catch(error => {
            this.messageTip(true, error.message, this.ForgetPanel, new Vec3(50, 950, 0));
        })
    }

    onClickGetCode(event: Event) {
        const NodeTarget = event.target as unknown as Node;
        const email = NodeTarget.parent.getChildByName("EditBoxUserName").getComponent(EditBox).string

        if (!GLOBALUtil.validateEmail(email)) {
            this.messageTip(true, "邮箱格式有误！", NodeTarget.parent, new Vec3(50, 950, 0));
            return;
        }

        const GetCodeData = {
            email: email
        }
        GLOBALUtil.sendXMLMessage('POST', GLOBALVar.SERVER_ADDRESS + "/Login/RequestGetCode", true, GetCodeData)
        .then(xhr => {
            const response = JSON.parse(xhr.response);
            console.log(response.msg);
            this.messageTip(true, response.msg, NodeTarget.parent, new Vec3(50, 950, 0));
        }).catch(error => { 
            console.log(error.message)
            this.messageTip(true, error.message, NodeTarget.parent, new Vec3(50, 950, 0));
        })
        
        //60秒之后才能重新获取验证码
        const GetCodeBtn: Button = NodeTarget.getComponent(Button);
        GetCodeBtn.interactable = false;
        const GetCodeLabel: Label = NodeTarget.getComponent(Label);
        let CountDown = 60;
        GetCodeLabel.string = CountDown.toString() + "秒后重试";
        this.schedule(() => {
            CountDown -= 1;
            GetCodeLabel.string = CountDown.toString() + "秒后重试";
            if (CountDown == 0) {
                this.unscheduleAllCallbacks();
                GetCodeLabel.string = "获取验证码";
                GetCodeBtn.interactable = true;
            }
        }, 1)
    }
    onCloseBG(evnet: Event) {
        let NodeTarget = evnet.target as unknown as Node;
        NodeTarget.parent.active = false;
    }

    private messageTip(isClose: boolean, msg:string, parent: Node, targetlPos: Vec3, destroy: boolean = false, messageType: number = 1, initialPos = new Vec3(-300, 950, 0), color: Color = new Color(255,255,255,255)) {
        if (this.MessageNode) this.MessageNode.destroy();
        let promise = GLOBALUtil.LoadMessage(isClose, msg, parent, targetlPos, destroy)
        promise.then((node: Node) => {
            this.MessageNode = node;
        })
    }
}


